﻿#ifndef __CARDAN_LIST_H__
#define __CARDAN_LIST_H__

#include <stdlib.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif  /*__cplusplus */

typedef struct _CARDAN_LIST_NODE {
	struct _CARDAN_LIST_NODE* pre;
	struct _CARDAN_LIST_NODE* next;
} CARDAN_LIST_NODE;


#define cd_list_create_head(cd_pkg_type) (cd_pkg_type*)(_cd_list_create_head());
#define cd_list_add_item(ph, pit) \
    { \
        char* _acd_pc = (char*)malloc(sizeof(CARDAN_LIST_NODE) + sizeof(*pit)); \
        memcpy(_acd_pc + sizeof(CARDAN_LIST_NODE), pit, sizeof(*pit)) ; \
        _cd_list_add_item((CARDAN_LIST_NODE*)ph, (CARDAN_LIST_NODE*)_acd_pc); \
    }

#define cd_list_delete_item(ph, pit, cd_pkg_type, cmp_fun) \
        { \
            CARDAN_LIST_NODE* _ph = (CARDAN_LIST_NODE*) ph; \
            CARDAN_LIST_NODE* _pIt = _ph->next; \
            while ( _ph != _pIt ) { \
                if (cmp_fun((cd_pkg_type*)((char*)_pIt + sizeof(CARDAN_LIST_NODE)), pit)) { \
                    _cd_list_delete_item((CARDAN_LIST_NODE*) ph, _pIt); \
					break; \
                } \
                _pIt = _pIt->next; \
            } \
        }

#define cd_list_release(ph) _cd_list_release((CARDAN_LIST_NODE*)ph)
#define cd_list_get_next_item(pcur, cd_pkg_type) ((cd_pkg_type*)(((CARDAN_LIST_NODE*)pcur)->next))



#define cd_list_for_each_item(ph, ppIt, cd_pkg_type) { \
	CARDAN_LIST_NODE* _ph = (CARDAN_LIST_NODE*)ph; \
	CARDAN_LIST_NODE* _pIt = _ph->next; \
	while(_ph != _pIt) { \
		*(ppIt) = (cd_pkg_type*)((char*)_pIt + sizeof(CARDAN_LIST_NODE))

#define  cd_list_for_each_item_end  _pIt = _pIt->next; \
		} \
	}

//start at pStart. so pStart should not be header.
#define cd_list_for_each_item_by_start(ph, pStart, ppIt, cd_pkg_type) { \
	CARDAN_LIST_NODE* _ph = (CARDAN_LIST_NODE*)ph; \
	CARDAN_LIST_NODE* _pIt = (CARDAN_LIST_NODE*)pStart; \
	while(_ph != _pIt) { \
	*(ppIt) = (cd_pkg_type*)((char*)_pIt + sizeof(CARDAN_LIST_NODE))

#define  cd_list_for_each_item_by_start_end  cd_list_for_each_item_end



void* _cd_list_create_head();
void _cd_list_add_item(CARDAN_LIST_NODE* ph, CARDAN_LIST_NODE* it);
int _cd_list_delete_item(CARDAN_LIST_NODE* ph, CARDAN_LIST_NODE* it);
void _cd_list_release(CARDAN_LIST_NODE* ph);


#ifdef __cplusplus
}
#endif  /*__cplusplus */

#endif
